﻿using System;
using System.IO;
using System.Net;
using System.Text;

namespace Quakk.Twitter
{
    public class TwitterApi
    {
        private const string sendTweetUrl = "http://twitter.com/statuses/update.xml";

        public string Username
        {
            get;
            set;
        }

        public string Password
        {
            get;
            set;
        }

        /// <summary>
        /// Opens the Url provided without authorising the user
        /// </summary>
        /// <param name="url">The Url to open</param>
        /// <returns>The response text from the Url</returns>
        public string OpenUrl(string url)
        {
            return OpenUrl(url, false);
        }

        /// <summary>
        /// Opens the Url provided authorising the user using the credentials if authorise=true
        /// </summary>
        /// <param name="url">The Url to open</param>
        /// <param name="authorise">Set to true if the Username/Password credentials is to be used</param>
        /// <returns>The response text from the Url</returns>
        public string OpenUrl(string url, bool authorise)
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);

            if (authorise)
            {
                NetworkCredential credentials = new NetworkCredential(Username, Password);
                webRequest.Credentials = credentials;
            }

            string responseText;
            WebResponse response = null;
            Stream stream = null;
            StreamReader reader = null;
            try
            {
                response = webRequest.GetResponse();
                stream = response.GetResponseStream();
                reader = new StreamReader(stream);
                responseText = reader.ReadToEnd();
            }
            catch (WebException ex)
            {
                throw new TwitterResponseException("Connection to Twitter was unsuccessful.", ex);
            }
            finally
            {
                if(response != null)
                {
                    response.Close();
                }
                if(stream != null)
                {
                    stream.Close();
                }
                if(reader != null)
                {
                    reader.Close();
                }
            }

            return responseText;
        }

        /// <summary>
        /// Send the specified text as a Tweet using the authenticated user's account
        /// </summary>
        /// <param name="message">The Message to send</param>
        public void SendTweet(string message)
        {
            string postString = "source=quakk&status=" + Uri.EscapeUriString(message);
            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] postData = encoding.GetBytes(postString);
            
            NetworkCredential credentials = new NetworkCredential(Username, Password);
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(sendTweetUrl);
            webRequest.Credentials = credentials;
            webRequest.Method = "POST";
            webRequest.ContentLength = postData.Length;
            webRequest.AllowWriteStreamBuffering = true;

            Stream outStream = null;
            StreamReader reader = null;
            WebResponse response = null;
            try
            {
                // Send the POST data
                outStream = webRequest.GetRequestStream();
                outStream.Write(postData, 0, postData.Length);
                outStream.Close();

                // Retrieve the response to complete the operation, 
                // but don't bother collecting the result
                response = webRequest.GetResponse();
                reader = new StreamReader(response.GetResponseStream());
                reader.ReadToEnd();
            }
            catch (WebException ex)
            {
                throw new TwitterResponseException("Connection to Twitter was unsuccessful.", ex);
            }
            finally
            {
                if(outStream != null)
                {
                    outStream.Close();
                }
                if(reader != null)
                {
                    reader.Close();
                }
                if(response != null)
                {
                    response.Close();
                }
            }
        }

        /// <summary>
        /// Download the image at the specified Url to the Path provided
        /// </summary>
        /// <param name="url">The Url location of the image</param>
        /// <param name="filePath">The Path to save to, including the filename</param>
        public void DownloadImage(string url, string filePath)
        {
            HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url);

            HttpWebResponse webResponse = null;
            Stream stream = null;
            BinaryReader reader = null;
            FileStream fileStream = null;
            BinaryWriter writer = null;

            try
            {
                webResponse = (HttpWebResponse) webRequest.GetResponse();
                stream = webResponse.GetResponseStream();

                reader = new BinaryReader(stream);
                fileStream = new FileStream(filePath, FileMode.Create);
                writer = new BinaryWriter(fileStream);

                // Write the contens of the web stream to the file stream
                byte[] buffer = new byte[webResponse.ContentLength];
                buffer = reader.ReadBytes(buffer.Length);
                writer.Write(buffer);
            }
            catch(WebException ex)
            {
                throw new TwitterResponseException("Connection to Twitter was unsuccessful.", ex);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
                if (fileStream != null)
                {
                    fileStream.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
                if (stream != null)
                {
                    stream.Close();
                }
                if (webResponse != null)
                {
                    webResponse.Close();
                }
            }
        }
    }

    public class TwitterResponseException : Exception
    {
        public TwitterResponseException(string message): base(message)
        { }

        public TwitterResponseException(string message, Exception innerException): base(message, innerException)
        { }
    }
}
